<?php

namespace app\admin\dao;

use app\common\model\LawCase;
use app\common\model\Trade;
use ShidianUtil\Thinkphp\Dao\DaoTrait;

/**
 * TradeDao 数据访问对象
 * Class TradeDao
 * @package app\dao
 * @method Trade findByPK(?int $id, $field = true)
 * @method \think\Collection selectAll(?int $page, ?int $page_size, $field = true)
 * @method Trade insertActive(array $params, array $allow_field = [])
 * @method Trade updateActive(Trade $model, array $params, array $allow_field = [])
 * @method Trade findAndUpdateActive(int $id, array $params, array $allow_field = [])
 * @method Trade updateActiveByClosure(\Closure $closure, array $params, array $allow_field = [])
 * @method void deleteModel(Trade $model)
 * @method void deleteById(int|array|\Closure $id, bool $force = false)
 * @link https://www.kancloud.cn/manual/thinkphp6_0/1037579
 * @link https://www.kancloud.cn/manual/think-orm/1257998
 * @link https://www.kancloud.cn/thinkphp/master-database-and-model/265551
 */
class TradeDao
{
    use DaoTrait;

    /**
     * @var Trade
     */
    private $baseModel;

    /**
     * TradeDao constructor.
     */
    public function __construct()
    {
        $this->baseModel = Trade::class;
    }

    /**
     * 待售案源列表
     * @param $categoryId
     * @param $provinceId
     * @param $cityId
     * @param $startTime
     * @param $endTime
     * @param $kw
     * @param int|null $page
     * @param int|null $page_size
     * @return array
     */
    public function listLawCases($categoryId, $provinceId, $cityId, $status, $startTime, $endTime, $kw, ?int $page, ?int $page_size): array
    {
        $tableName = Trade::getTable();

        $query = Trade::leftJoin('law_case lc', "$tableName.lawCaseId=lc.id")
                      ->where("$tableName.tradeType", TRADE_LAS_CASE)
                      ->when(is_id($categoryId), fn($query) => $query->where('lc.categoryId', $categoryId))
                      ->when(is_id($provinceId), fn($query) => $query->where('lc.provinceId', $provinceId))
                      ->when(is_id($cityId), fn($query) => $query->where('lc.cityId', $cityId))
                      ->when(is_numeric($startTime), fn($query) => $query->where('lc.created', '>=', $startTime))
                      ->when(is_numeric($endTime), fn($query) => $query->where('lc.created', '<=', $endTime))
                      ->when(not_blank($kw), fn($query) => $query->search('lc.uid|lc.ask', $kw));

        // 1 待付款 2 已付款 6退款（3 待审核 4 退款成功 5 退款失败）
        if ($status == 1) {
            $query->where('payStatus', Trade::UNPAID);
        } elseif ($status == 2) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::NOTREFUND);
        } elseif ($status == 3) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUNDING)
                  ->where('refundCheckStatus', Trade::UNCHECKED);
        } elseif ($status == 4) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUNDED);
        } elseif ($status == 5) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUND_FAILED);
        } elseif ($status == 6) {
            $query->where('payStatus', Trade::PAID)
                  ->whereIn('refundStatus', [Trade::REFUNDING, Trade::REFUNDED, Trade::REFUND_FAILED]);
        }

        $query->tableField(true, $tableName)
              ->with([
                  'member' => fn($query) => $query->shortMember()->field(['phone']),
                  'lawCase' => fn($query) => $query->with([
                      'category' => fn($query) => $query->field(['id', 'name']),
                      'province' => fn($query) => $query->shortArea(),
                      'city' => fn($query) => $query->shortArea(),
                      'member' => fn($query) => $query->shortMember(),
                      'creator' => fn($query) => $query->shortMember()->field(['phone']),
                      'money',
                      'days',
                  ])
              ])
              ->withAttr([
                  'payMethodStr' => fn($value, $data) => account_type_str($data['payMethod']),
              ])
              ->append(['payMethodStr'])
              ->order("$tableName.id", 'DESC')
              ->paging($page, $page_size);

        return listOutput($query, $page_size);
    }

    /**
     * 待售案源列表统计
     * @param $categoryId
     * @param $provinceId
     * @param $cityId
     * @param $startTime
     * @param $endTime
     * @param $kw
     * @param int|null $page
     * @param int|null $page_size
     * @return array
     */
    public function statisticsListLawCases($categoryId, $provinceId, $cityId, $status, $startTime, $endTime, $kw): array
    {
        $tableName = Trade::getTable();

        $query = Trade::leftJoin('law_case lc', "$tableName.lawCaseId=lc.id")
                      ->where("$tableName.tradeType", TRADE_LAS_CASE)
                      ->when(is_id($categoryId), fn($query) => $query->where('lc.categoryId', $categoryId))
                      ->when(is_id($provinceId), fn($query) => $query->where('lc.provinceId', $provinceId))
                      ->when(is_id($cityId), fn($query) => $query->where('lc.cityId', $cityId))
                      ->when(is_numeric($startTime), fn($query) => $query->where('lc.created', '>=', $startTime))
                      ->when(is_numeric($endTime), fn($query) => $query->where('lc.created', '<=', $endTime))
                      ->when(not_blank($kw), fn($query) => $query->search('lc.uid|lc.ask', $kw));

        // 1 待付款 2 已付款 6退款（3 待审核 4 退款成功 5 退款失败）
        if ($status == 1) {
            $query->where('payStatus', Trade::UNPAID);
        } elseif ($status == 2) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::NOTREFUND);
        } elseif ($status == 3) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUNDING)
                  ->where('refundCheckStatus', Trade::UNCHECKED);
        } elseif ($status == 4) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUNDED);
        } elseif ($status == 5) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUND_FAILED);
        } elseif ($status == 6) {
            $query->where('payStatus', Trade::PAID)
                  ->whereIn('refundStatus', [Trade::REFUNDING, Trade::REFUNDED, Trade::REFUND_FAILED]);
        }

        $query2 = LawCase::when(is_id($categoryId), fn($query) => $query->where('categoryId', $categoryId))
                         ->when(is_id($provinceId), fn($query) => $query->where('provinceId', $provinceId))
                         ->when(is_id($cityId), fn($query) => $query->where('cityId', $cityId))
                         ->when(is_numeric($startTime), fn($query) => $query->where('created', '>=', $startTime))
                         ->when(is_numeric($endTime), fn($query) => $query->where('created', '<=', $endTime))
                         ->when(not_blank($kw), fn($query) => $query->search('uid|ask', $kw));

        return [
            'new_count' => $query2->count(),
            'sold_money_sum' => (clone $query)->where('payStatus', Trade::PAID)->whereIn('refundStatus', [Trade::NOTREFUND, Trade::REFUNDING, Trade::REFUND_FAILED])->sum('payMoney'),
            'unstarted_count' => (clone $query2)->where('isPublish', '1')->where('publishTime', '<', time())->count(),
            'set_money_sum' => (clone $query2)->where('isPublish', '1')->where('publishTime', '>=', time())->sum('totalPrice'),
        ];
    }

    /**
     * 订单列表
     * @param $provinceId
     * @param $cityId
     * @param $payMethod
     * @param $categoryId
     * @param $serverId
     * @param $status
     * @param $startTime
     * @param $endTime
     * @param $kw
     * @param $page
     * @param $page_size
     * @return array
     */
    public function listTrades($memberId, $provinceId, $cityId, $payMethod, $categoryId, $serverId, $status, $startTime, $endTime, $kw, $page, $page_size): array
    {
        // 显示的订单类型
        $tradeTypes = [
            TRADE_BALANCE_RECHARGE,
            TRADE_CONSULTING_SERVER,
            TRADE_REWARD,
            TRADE_RED_PACKET,
            TRADE_LAWSUIT,
            TRADE_LANDING,
        ];

        $tableName = Trade::getTable();

        $query = Trade::when(is_id($memberId), fn($query) => $query->where("$tableName.memberId", $memberId))
                      ->when(is_id($payMethod), fn($query) => $query->where('payMethod', $payMethod))
                      ->when(is_id($categoryId) || is_id($serverId) || is_id($provinceId) || is_id($cityId) || not_blank($kw),
                          fn($query) => $query->leftJoin('consulting c', "$tableName.consultingId=c.id")
                                              ->when(is_id($provinceId), fn($query) => $query->where('c.provinceId', $provinceId))
                                              ->when(is_id($cityId), fn($query) => $query->where('c.cityId', $cityId))
                                              ->when(is_id($categoryId), fn($query) => $query->where('c.categoryId', $categoryId))
                                              ->when(is_id($serverId), fn($query) => $query->where("$tableName.serverId", $serverId))
                                              ->when(not_blank($kw), fn($query) => $query->leftJoin('member m', "$tableName.memberId=m.id")
                                                                                         ->search("$tableName.orderNo|c.ask|m.nickname|m.realname|m.phone", $kw)))
                      ->when(is_numeric($startTime), fn($query) => $query->where("$tableName.created", '>=', $startTime))
                      ->when(is_numeric($endTime), fn($query) => $query->where("$tableName.created", '<=', $endTime));

        // 1.未付款 2.进行中 3.结算中 4.已完成 5.申请退款 6.已退款 7.已拒绝退款 8.已取消
        // 100全部退款订单
        if ($status == 1) {
            $query->where('payStatus', Trade::UNPAID);
        } elseif ($status == 2) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::NOTREFUND)
                  ->whereNull('endTime');
        } elseif ($status == 3) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::NOTREFUND)
                  ->where('settleStatus', Trade::UNSETTLED)
                  ->whereNotNull('endTime')
                  ->where('endTime', '<=', time());
        } elseif ($status == 4) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::NOTREFUND)
                  ->whereIn('settleStatus', [Trade::NOTSETTLE, Trade::SETTLED])
                  ->whereNotNull('endTime');
        } elseif ($status == 5) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUNDING)
                  ->where('refundCheckStatus', Trade::UNCHECKED);
        } elseif ($status == 6) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUNDED);
        } elseif ($status == 7) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUND_FAILED);
        } elseif ($status == 8) {
            $query->where('payStatus', Trade::CANCELLED);
        } elseif ($status == 100) {
            $query->where('payStatus', Trade::PAID)
                  ->whereIn('refundStatus', [Trade::REFUNDING, Trade::REFUNDED, Trade::REFUND_FAILED]);
        } else {
            // 全部

            // $query->where('payStatus', '<>', Trade::CANCELLED);
        }

        $query->whereIn('tradeType', $tradeTypes);

        $query->tableField(true, $tableName)
              ->with([
                  'member' => fn($query) => $query->shortMember(),
                  'consulting' => fn($query) => $query->field(['id', 'ask', 'lawyerId', 'provinceId', 'cityId', 'categoryId', 'lawyerMoney'])
                                                      ->with([
                                                          'province' => fn($query) => $query->shortArea(),
                                                          'city' => fn($query) => $query->shortArea(),
                                                          'lawyer' => fn($query) => $query->shortLawyer(),
                                                          'category' => fn($query) => $query->field(['id', 'name']),
                                                      ]),
              ])->withAttr([
                'payMethodStr' => fn($value, $data) => account_type_str($data['payMethod']),
            ])->append(['payMethodStr', 'status', 'statusTime', 'statusStr', 'canPunish'])
              ->order("$tableName.id", 'DESC')
              ->paging($page, $page_size);

        return listOutput($query, $page_size);
    }

    /**
     * 订单列表统计
     * @param $memberId
     * @param $provinceId
     * @param $cityId
     * @param $payMethod
     * @param $categoryId
     * @param $serverId
     * @param $status
     * @param $startTime
     * @param $endTime
     * @param $kw
     * @return array
     */
    public function statisticsListTrades($memberId, $provinceId, $cityId, $payMethod, $categoryId, $serverId, $status, $startTime, $endTime, $kw): array
    {
        // 显示的订单类型
        $tradeTypes = [TRADE_BALANCE_RECHARGE, TRADE_CONSULTING_SERVER, TRADE_REWARD, TRADE_RED_PACKET,];

        $tableName = Trade::getTable();

        $query = Trade::when(is_id($memberId), fn($query) => $query->where("$tableName.memberId", $memberId))
                      ->when(is_id($payMethod), fn($query) => $query->where('payMethod', $payMethod))
                      ->when(is_id($categoryId) || is_id($serverId) || is_id($provinceId) || is_id($cityId) || not_blank($kw),
                          fn($query) => $query->leftJoin('consulting c', "$tableName.consultingId=c.id")
                                              ->when(is_id($provinceId), fn($query) => $query->where('c.provinceId', $provinceId))
                                              ->when(is_id($cityId), fn($query) => $query->where('c.cityId', $cityId))
                                              ->when(is_id($categoryId), fn($query) => $query->where('c.categoryId', $categoryId))
                                              ->when(is_id($serverId), fn($query) => $query->where('c.consultingServerId', $serverId))
                                              ->when(not_blank($kw), fn($query) => $query->leftJoin('member m', "$tableName.memberId=m.id")
                                                                                         ->search("$tableName.orderNo|c.ask|m.nickname|m.realname|m.phone", $kw)))
                      ->when(is_numeric($startTime), fn($query) => $query->where("$tableName.created", '>=', $startTime))
                      ->when(is_numeric($endTime), fn($query) => $query->where("$tableName.created", '<=', $endTime));

        // 改成 1.未付款 2.进行中 3.结算中 4.已完成 5.申请退款 6.已退款 7.已拒绝退款 100全部退款订单
        if ($status == 1) {
            $query->where('payStatus', Trade::UNPAID);
        } elseif ($status == 2) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::NOTREFUND)
                  ->whereNull('endTime');
        } elseif ($status == 3) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::NOTREFUND)
                  ->where('settleStatus', Trade::UNSETTLED)
                  ->whereNotNull('endTime')
                  ->where('endTime', '<=', time());
        } elseif ($status == 4) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::NOTREFUND)
                  ->whereIn('settleStatus', [Trade::NOTSETTLE, Trade::SETTLED])
                  ->whereNotNull('endTime');
        } elseif ($status == 5) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUNDING)
                  ->where('refundCheckStatus', Trade::UNCHECKED);
        } elseif ($status == 6) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUNDED);
        } elseif ($status == 7) {
            $query->where('payStatus', Trade::PAID)
                  ->where('refundStatus', Trade::REFUND_FAILED);
        } elseif ($status == 8) {
            $query->where('payStatus', Trade::CANCELLED);
        } elseif ($status == 100) {
            $query->where('payStatus', Trade::PAID)
                  ->whereIn('refundStatus', [Trade::REFUNDING, Trade::REFUNDED, Trade::REFUND_FAILED]);
        } else {
            // 全部

            $query->where('payStatus', '<>', Trade::CANCELLED);
        }

        $query->whereIn('tradeType', $tradeTypes);


        return [
            'order_count' => $query->count(),
            'order_money_sum' => $query->sum('payMoney'),
            'lawyer_money_sum' => $query->sum('settleLawyerMoney'),
            'refunded_money_sum' => (clone $query)->whereIn('refundStatus', [Trade::REFUNDED])->sum('payMoney'),
            'unrefunded_money_sum' => (clone $query)->where('refundStatus', Trade::REFUNDING)->where('refundCheckStatus', Trade::UNCHECKED)->sum('payMoney'),
        ];
    }
}
